home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / asm_n_z.arj / STOCHAIN.ASM < prev    next >
Assembly Source File  |  1986-10-24  |  28KB  |  807 lines

  1.                  PAGE 60,132 
  2.                 ;program to chain and form DOS storage blocks
  3.                 ; Usage is: STOCHAIN 
  4.  
  5. sb              SEGMENT AT 0       ;map of storage block header paragraph
  6. sbkind          DB      ' '        ;Type of storage block: M or Z
  7. sbpsp           DW       0         ;PSP segment address
  8. sblength        DW       0         ;SB length in paragraphs
  9. sbfill          DB       11 DUP(0) ;filler
  10.  
  11.  
  12.  
  13.                 ORG      sbkind
  14. pspretint       DW       ?          ;int 20
  15. pspmemsize      DW       ?          ;size of memory in paragraphs
  16. pspresv         DB       ?
  17.                 ORG      5h
  18. pspcalldosfunct DB       ?          ;long call to dos function dispatcher
  19. pspdosfunct     DD       ?          ;IP:CS of dos function dispatcher
  20.                 ORG      0Ah
  21. pspdosterminate DD       ?          ;IP:CS of:dos terminate 
  22.                 ORG      0Eh
  23. pspdosctrlbreak DD       ?          ;         ctrl break address
  24.                 ORG      12h
  25. pspdoscrtclerr  DD       ?          ;         critical error handler
  26.                 ORG      18h
  27. pspdosdefhandle DD       20 dup(?)  ;         DOS 2.0 - 20 file handles
  28.                                     ;         DOS 3.0 - default file handles
  29.                 ORG      2Ch
  30. pspenv          DW       ?          ;segment address of environment
  31.                 ORG      32h
  32. psphandlecount  DW       ?          ;number of handles in table (DOS 3.0)
  33.                 ORG      34h
  34. psphandles      DW       ?          ;offset of handle table in CS (DOS 3.0)
  35.                 ORG      50h
  36. pspdosfunction  DW       ?          ;invoke dos function dispatcher
  37.                 ORG      5Ch
  38. pspfcb1         DB       ?          ;first fcb
  39.                 ORG      6Ch
  40. pspfcb2         DB       ?          ;second fcb
  41.                 ORG      80h
  42. pspparm         DB       ?          ;unformatted paramter area
  43.                 ORG      0FFh
  44. pspend          EQU      $
  45.  
  46. sb              ENDS
  47.  
  48. code_seg        SEGMENT
  49.  
  50.                 ASSUME    CS:code_seg,DS:code_seg,ES:sb
  51.  
  52. cr              equ       13
  53. lf              equ       10
  54.  
  55. myretint        DW       ?          ;int 20
  56.                 ORG      50h
  57. mydosfunction   DW       ?          ;invoke dos function dispatcher
  58.                 ORG       100h
  59.  
  60. code            PROC      far
  61.  
  62.                 jmp       program
  63.                 db        'Copyright 1986 by Arnold B. Krueger GPW MI, 48236'
  64. typestring      proc near 
  65.                 push ax
  66.                 mov  ax,0900h
  67.                 int  21h
  68.                 pop  ax
  69.                 ret
  70. typestring      endp
  71.  
  72. getfirstsb      PROC near       ;get first storage block, ES will point to it
  73.                 PUSH AX
  74.                 PUSH BX
  75.                 MOV  AX,5200h       
  76.                 INT  21h        ;ES:BX points to memory block anchor+2
  77.                 DEC  BX
  78.                 DEC  BX
  79.                 MOV  ES,ES:[BX] ;get first memory block address into ES
  80.                 POP  BX
  81.                 POP  AX
  82.                 RET
  83. getfirstsb      ENDP
  84.  
  85. getnextsb       PROC near
  86.                 PUSH AX
  87.                 MOV  AX,ES             ;get current paragraph
  88.                 ADD  AX,[SBLENGTH]     ;add in number of paragraphs
  89.                 INC  AX                ;add 1 for header
  90.                 MOV  ES,AX             ;set new extra segment address
  91.                 POP  AX
  92.                 RET
  93. getnextsb       ENDP
  94.  
  95. hexformat       equ  $
  96. hexaddrhi       dw   0
  97. hexaddrlo       dw   0
  98.                 db   ':0  '
  99. hexdata         dw   18 dup(0) 
  100. hexdataend      db   '*$'
  101. hexend          db   '*'
  102. crlf            db   cr,lf,'$'
  103. indent          db   5 dup(' '),'$'
  104.  
  105. asciizl         proc near              ;string, length in CX
  106.                                        ; at ES:DI searched for 0h
  107.                                        ;new length in CX
  108.                 push  ax
  109.                 xor   al,al            ;search for zero
  110.                 call  charstrl
  111.                 pop   ax
  112.  
  113.                 ret
  114.  
  115. asciizl         endp
  116.  
  117. charstrl        proc  near             ;string length in CX
  118.                                        ;string at ES:DI searched for char in AL
  119.                                        ;new length in CX
  120.                 push  ax
  121.                 push  di               ;save register
  122.  
  123.                 push  cx               ;save cx
  124.                 repnz scasb            ;do search
  125.                 jcxz  charsterror      ;if cx exhausted, may be error
  126. charsthit:
  127.                 mov   ax,cx            ;save count remaining
  128.                 pop   cx               ;restore old cx
  129.                 sub   cx,ax            ;subtract length
  130.                 dec   cx               ;knock off 1 for failed test
  131.                 jcxz  charstnull       ;if zero length, error
  132.                 clc                    ;clear carry flag
  133.                 jmp   charstexit       ;and exit
  134.                 
  135. charsterror:
  136.                 dec   di               ;back up
  137.                 cmp   al,es:[di]       ;check last byte 
  138.                 je    charsthit        ;if what we want, use it
  139.  
  140.                 pop   cx               ;pull off saved cx
  141. charstnull:
  142.                 stc                    ;set error flag
  143. charstexit:     
  144.                 pop   di               ;restore registers
  145.                 pop   ax
  146.                 ret
  147.  
  148. charstrl        endp
  149.  
  150. hextocharlist   db   '0123456789ABCDEF'
  151.  
  152. hextochar       PROC near              ;AL (hex) -> AX (characters)
  153.                 PUSH SI
  154.                 PUSH DX
  155.                 PUSH CX
  156.                 PUSH AX
  157.                 XOR  DX,DX
  158.                 AND  AX,0fh            ;isolate low nibble
  159.                 ADD  AX,offset hextocharlist
  160.                 MOV  SI,AX             ;get address of character
  161.                 MOV  DH,[SI]           ;get character
  162.                 POP  AX
  163.                 AND  AX,0f0h           ;isolate high nibble
  164.                 MOV  CL,4
  165.                 SHR  AX,CL
  166.                 ADD  AX,offset hextocharlist
  167.                 MOV  SI,AX             ;get address of character
  168.                 OR   DL,[SI]           ;get character
  169.                 MOV  AX,DX
  170.                 POP  CX
  171.                 POP  DX
  172.                 POP  SI
  173.                 RET
  174. hextochar       ENDP 
  175.  
  176. Hexline         proc near         ;type paragraph at ES: in hex
  177.                 push si
  178.                 push cx
  179.                 push ax
  180.                 push es
  181.                 pop  ax
  182.                 call hextochar    ;get low byte
  183.                 mov  hexaddrlo,ax
  184.                 push es
  185.                 pop  ax
  186.                 mov  al,ah        ;get high byte
  187.                 call hextochar
  188.                 mov  hexaddrhi,ax
  189.                 xor  si,si
  190.                 mov  di,offset hexdata
  191.                 mov  cx,4
  192. hexparaloop:                      ;loop 4 times per paragraph
  193.                 push cx
  194.                 mov  cx,4
  195. hexwordloop:                      ;loop 4 times per doubleword
  196.                 mov  al,es:[si]
  197.                 call hextochar
  198.                 mov  ds:[di],ax
  199.                 inc  di
  200.                 inc  di
  201.                 inc  si
  202.                 loop hexwordloop 
  203.  
  204.                 mov  byte ptr ds:[di],' '
  205.                 inc  di
  206.                 pop  cx
  207.                 loop hexparaloop
  208.  
  209.                 pop  ax
  210.                 pop  cx
  211.                 pop  si
  212.                 ret
  213. hexline         endp 
  214.  
  215. chartype        proc near          ;type CX bytes at ES:DI if typable
  216.                 stc                ;possible error
  217.                 jcxz chartypeexit  ;if nothing to type, exit
  218.                 push ax
  219.                 push cx
  220.                 push dx
  221.                 push di
  222. chartypeloop:
  223.                 mov  dl,es:[di]
  224.                 cmp  dl,126        ;printer/console
  225. ;               cmp  dl,254        ;console only
  226.                 ja   chartypefix               
  227.                 cmp  dl,31
  228.                 ja   chartypeit
  229.                 jmp  chartypefix   ;printer/console
  230.                 cmp  dl,26         ;console only
  231.                 ja   chartypefix
  232.                 cmp  dl,13
  233.                 ja   chartypeit
  234.                 cmp  dl,6
  235.                 ja   chartypefix
  236.                 cmp  dl,0
  237.                 ja   chartypeit
  238.  
  239. chartypefix:    mov  dl,'.'
  240. chartypeit:     mov  ax,0200h
  241.                 int  21h
  242.                 inc  di
  243.                 loop chartypeloop
  244.  
  245.                 clc                ;no error
  246.  
  247.                 pop  di
  248.                 pop  dx
  249.                 pop  cx
  250.                 pop  ax
  251. chartypeexit:
  252.                 ret
  253. chartype        endp     
  254.  
  255. hextype         proc near       ;proc to hex type data at ES:0
  256.                 push ax
  257.                 push cx 
  258.                 push dx
  259.                 push di
  260.                 call hexline
  261.                 mov  dx,offset hexformat
  262.                 call typestring
  263.                 mov  cx,16
  264.                 xor  di,di
  265.                 call chartype
  266.                 mov  dx,offset hexend
  267.                 call typestring
  268.                 pop  di
  269.                 pop  dx
  270.                 pop  cx
  271.                 pop  ax
  272.                 ret
  273. hextype         endp
  274.  
  275. sbbackup       proc  near           ;decrement es by one
  276.                push   ax            ;save work register
  277.  
  278.                push   es            ;back up
  279.                pop    ax
  280.                dec    ax            ;and address storage block header
  281.                push   ax
  282.                pop    es
  283.  
  284.                pop    ax            ;restore work register
  285.                ret
  286. sbbackup       endp               
  287.  
  288. sbinc          proc  near           ;increment es by one
  289.                push   ax            ;save work register
  290.  
  291.                push   es            
  292.                pop    ax
  293.                inc    ax            ;and address storage block contents
  294.                push   ax                                       
  295.                pop    es
  296.  
  297.                pop    ax            ;restore work register
  298.                ret
  299. sbinc       endp               
  300.  
  301.  
  302. progenvmsg     db   'Program environment block questionable',cr,lf,'$'
  303.  
  304. progenvend     proc near            ;find end of environment in ES:0
  305.                push   ax            ;update DI, remaining length in CX
  306.                push   bx
  307.                push   dx
  308.                push   es
  309.  
  310.                call   sbbackup      ;backup over storage block header
  311.                mov    bx,[sblength] ;get length of storage block
  312.                pop    es            ;restore ES
  313.                push   es            ;restore stack
  314.                mov    cl,4          ;multiply BX by 16
  315.                shl    bx,cl
  316.                mov    cx,bx         ;number of words in environment
  317.                xor    di,di
  318.                xor    ax,ax
  319.                cld                  ;scan forward
  320. progenvscan:                        ;loop through environment
  321.                scasw                ;compare a word at ES:DI
  322.                jz     progenvfinis  ;if equal, exit loop
  323.                dec    di            ;go forward only 1 byte
  324.                loop   progenvscan   ;and scan on
  325. progenvfinis:
  326.                jcxz   progenvshort  ;if we ran out, error
  327.                dec    di            ;back up a byte
  328.                mov    ax,1          ;now look for '0001'h
  329. progenvedit:
  330.                scasw
  331.                jz     progenvprog   ;got one? then go on
  332.                dec    di            ;back up a byte
  333.                loop   progenvedit
  334.                jcxz   progenvshort
  335. progenvprog:
  336.                clc                  ;clear carry flag
  337.                                     ;ES:DI points to program name
  338.                jmp    progenvexit   
  339.  
  340. progenvshort:
  341.                mov    dx,offset progenvmsg
  342. progenverror:
  343.                call   typestring
  344.                stc                  ;set carry flag
  345. progenvexit:             
  346.                pop    es            ;restore registers
  347.                pop    dx
  348.                pop    bx
  349.                pop    ax
  350.                ret
  351. progenvend     endp
  352.  
  353. progtypedos2msg    db   'Program name not available in DOS 2.0',cr,lf,'$'
  354. progtypeformat     db   'Program name:$'
  355. progtypenameover   db   '     program name overlaid',cr,lf,'$'
  356.  
  357. progtypename   proc   near          ;es points to environment
  358.                push  dx
  359.                push  bx
  360.                push  ax
  361.                mov   ah,30h         ;get release number
  362.                int   21h
  363.                cmp   al,02h         ;above dos 2.0?
  364.                jna   progtypedos2
  365.  
  366.                call progenvend      ;find environment end in ES:DI, length: CX
  367.  
  368.                jc   progtypenoname  ;if not found, just exit
  369.  
  370.                mov  dx,offset progtypeformat  ;type out header
  371.                call typestring
  372.                mov  dx,offset indent
  373.                call typestring
  374.                call asciizl         ;length of asciiz string at ES:DI to CX
  375.                jc   progtypenoname
  376.  
  377.                cmp  cx,3              ;minimum length of individual item
  378.                jb   progtypenoname
  379.  
  380.                cmp  cx,255            ;maximum length of individual item
  381.                ja   progtypenoname
  382.  
  383.                call chartype
  384.  
  385.                mov  dx,offset crlf
  386.                call typestring
  387.                clc
  388.                jmp  progtypenameexit
  389.  
  390. progtypedos2:
  391.                mov  dx,offset progtypedos2msg
  392.                call typestring
  393.                stc
  394.                jmp  progtypenameexit
  395.  
  396. progtypenoname:
  397.                mov  dx,offset progtypenameover
  398.                call typestring
  399.                stc
  400.  
  401. progtypenameexit:
  402.                pop  ax 
  403.                pop  bx
  404.                pop  dx
  405.                ret
  406.  
  407. progtypename   endp
  408.  
  409. progtypeenvformat  db   'Program environment string at: '
  410. progtypeenvaddhi   dw   0
  411. progtypeenvaddlo   dw   0
  412.                    db   ':0',cr,lf,'$'
  413.  
  414. progtypeenvbadmsg  db   'Program environment string overlaid',cr,lf,'$'
  415.  
  416. progtypeenv    proc near            ;type out environment strings at ES:0
  417.  
  418.                push ax
  419.                push cx
  420.                push di
  421.                push dx
  422.  
  423.                push es
  424.                pop  ax
  425.                call hextochar 
  426.                mov  progtypeenvaddlo,ax
  427.                push es
  428.                pop  ax
  429.                mov  al,ah
  430.                call hextochar 
  431.                mov  progtypeenvaddhi,ax
  432.  
  433.                mov  dx,offset progtypeenvformat
  434.                call typestring
  435.  
  436.                xor  di,di           ;type out environment strings
  437.  
  438.                cmp  byte ptr es:[di],0  ;common type of trashing of environment
  439.                je   progtypeenvbad
  440.  
  441.                xor  ax,ax           ;make ax zero for end of environment search
  442.  
  443. progtypeenvloop:
  444.                mov  dx,offset indent  ;print out some blanks
  445.                call typestring
  446.                mov  cx,128            ;search a ways
  447.                call asciizl           ;get length of asciiz string
  448.                jc   progtypeenvbad    ;if error, skip out
  449.  
  450.                cmp  cx,3              ;minimum length of individual item
  451.                jb   progtypeenvbad
  452.  
  453.                cmp  cx,255            ;maximum length of individual item
  454.                ja   progtypeenvbad
  455.                
  456.                call chartype          ;type it out
  457.                jc   progtypeenvbad    ;if error, skip out
  458.  
  459.                add  di,cx             ;add in its length
  460.                mov  dx,offset crlf    ;print out a cr, lf
  461.                call typestring
  462.  
  463.                scasw                  ;look at next word
  464.                jz   progtypeenvend    ;if zero, end of environment
  465.                dec  di                ;otherwise back up a byte
  466.                jmp  progtypeenvloop   ;and look again
  467.  
  468. progtypeenvbad:
  469.                mov  dx,offset progtypeenvbadmsg  ;complain about environment
  470.                call typestring
  471.                stc                     ;return error
  472.  
  473. progtypeenvend:
  474.                pop  dx
  475.                pop  di
  476.                pop  cx
  477.                pop  ax
  478.                ret
  479.  
  480. progtypeenv    endp 
  481.  
  482. progtypeparmformat db   'Program calling parameters: $'
  483. progtypeparmnone   db   '(none)',cr,lf,'$'
  484.  
  485. progtypeparm   proc near         ;type out parm area of PSP at ES:0
  486.                push ax
  487.                push cx
  488.                push di
  489.                push dx
  490.  
  491.                mov  dx,offset progtypeparmformat
  492.                call typestring        ;print out heading
  493.  
  494.                mov  di,offset pspparm   ;ES:DI to parameter list
  495.                mov  al,es:[di]          ;get parm length
  496.                cmp  al,127              ;if impossible, skip out
  497.                ja   progtypenoparm    
  498.  
  499.                inc  di                ;now look at actual data
  500.                mov  cx,255 
  501.                mov  al,cr             ;look for carriage return
  502.                call charstrl          ;get actual length of parms
  503.                jc   progtypenoparm    ;error detected, forget it
  504.  
  505.                jcxz progtypenoparm    ;if null parm,  skip out
  506.                cmp  cx,127            ;if impossible, skip out
  507.                ja   progtypenoparm
  508.  
  509.                call chartype          ;if good, type out
  510.  
  511.                mov  dx,offset crlf
  512.                call typestring
  513.                clc
  514.                jmp  progtypeparmexit
  515.  
  516. progtypenoparm:      ;no parms
  517.                mov  dx,offset progtypeparmnone
  518.                call typestring
  519.                stc
  520.  
  521. progtypeparmexit:
  522.                pop  dx
  523.                pop  di
  524.                pop  cx
  525.                pop  ax
  526.                ret
  527. progtypeparm   endp
  528.  
  529. progtypenoenvmsg   db   'Program has no environment block',cr,lf,'$'
  530. progtypefirstprog  db   0
  531. yes                equ  1
  532. progtypedospsp     dw   0    ;segment address of first command.com resident part
  533.  
  534. progtype       proc near         ;format program storage block at ES:0
  535.                push ax
  536.  
  537.                push bx
  538.                push cx
  539.                push dx
  540.                push es
  541.  
  542.                clc
  543.                call sbinc        ;program follows SB header
  544.                push es           ;save ES in BX
  545.                pop  bx
  546.  
  547.                mov  ax,[mydosfunction] 
  548.                cmp  ax,[pspdosfunction] ;check PSP validity                
  549.                jne  progtypenoenv       ;around byte 0h
  550.  
  551.                mov  ax,[myretint]
  552.                cmp  ax,[pspretint]      ;check PSP validity
  553.                jne  progtypenoenv       ;if invalid, skip looking for env
  554.  
  555.                cmp  progtypefirstprog,yes  ;is this the first program
  556.                je   progtypenotdos
  557.                mov  progtypefirstprog,yes
  558.                push ES
  559.                pop  AX
  560.                mov  progtypedospsp,AX   ;save first resident command.com
  561.  
  562. progtypenotdos:
  563.                mov  ax,[pspenv]         ;get environment of program
  564.                cmp  ax,0
  565.                je   progtypenoenv       ;if no environment, say so
  566.                push ax
  567.                pop  es                  ;ES points to environment
  568.  
  569.                call progtypename        ;format program name from environment
  570.  
  571.                call progtypeenv         ;format environment strings
  572.  
  573.                push bx
  574.                pop  es                  ;back to looking at program PSP
  575.  
  576.                call progtypeparm        ;format program parm area
  577.  
  578.                jmp  progtypeend
  579.  
  580.  
  581. progtypenoenv: ;no environment (!!)
  582.                mov  dx,offset progtypenoenvmsg
  583.                call typestring
  584.                stc
  585.  
  586. progtypeend:
  587.                pop  es
  588.                pop  dx
  589.                pop  cx
  590.                pop  bx
  591.                pop  ax
  592.  
  593.                ret
  594. progtype       endp
  595.  
  596. sbformat       equ  $
  597.                db   'Storage block at:'
  598. sbaddrhi       dw   0
  599. sbaddrlo       dw   0
  600.                db   ':0  PSP of owner at:' 
  601. sbpsphi        dw   0
  602. sbpsplo        dw   0
  603.                db   ':0  Block length:' 
  604. sblengthhi     dw   0
  605. sblengthlo     dw   0
  606. sbcrlf         db   cr,lf,'$'
  607.  
  608. sbglobalmsg    db   'Storage block is the global environment',cr,lf,'$'
  609. sbnotprogmsg   db   'Storage block is not a program',cr,lf,'$'
  610. sbsystemmsg    db   'Storage block is system owned',cr,lf,'$'
  611. sbfreemsg      db   'Storage block is free',cr,lf,'$'
  612. sbconfigmsg    db   'Storage block belongs to CONFIG.SYS',cr,lf,'$'
  613. sbprogmsg      db   'Storage block is a program',cr,lf,'$'
  614. sbproghead     db   'Program PSP contents:',cr,lf,'$'
  615. sbdatahead     db   'Storage block contents: (first 128 bytes)',cr,lf,'$'
  616. sbhead         db   'Storage header contents:',cr,lf,'$'
  617.  
  618. sbtype          proc  near        ;format out block
  619.                 push ax           ;save registers
  620.                 push cx
  621.                 push dx
  622.                 push es                    ;format out block header
  623.                 pop  ax                    ;format block address
  624.                 call hextochar                 ;get low byte
  625.                 mov  sbaddrlo,ax
  626.                 push es
  627.                 pop  ax
  628.                 mov  al,ah                     ;get high byte
  629.                 call hextochar
  630.                 mov  sbaddrhi,ax
  631.  
  632.                 mov  al,byte ptr sblength  ;format block length
  633.                 call hextochar 
  634.                 mov  sblengthlo,ax
  635.                 mov  al,byte ptr sblength+1 
  636.                 call hextochar 
  637.                 mov  sblengthhi,ax
  638.  
  639.                 mov  al,byte ptr sbpsp     ;format block psp pointer
  640.                 call hextochar 
  641.                 mov  sbpsplo,ax
  642.                 mov  al,byte ptr sbpsp+1 
  643.                 call hextochar 
  644.                 mov  sbpsphi,ax
  645.  
  646.                 mov  dx,offset sbformat    ;type out formatted data
  647.                 call typestring
  648.  
  649.                 mov  ax,[sbpsp]            ;get PSP of owner
  650.                 cmp  ax,0                  ;if zero, it is free
  651.                 je   sbfree
  652.  
  653.                 cmp  ax,8                  ;if PSP of owner is at 8
  654.                 je   sbconfig              ;block owned by config.sys
  655.  
  656.                 cmp  ax,progtypedospsp     ;is owner command.com
  657.                 je   sbglobalenv
  658.                                            ;get address of SB
  659.                 push es
  660.                 pop  ax
  661.  
  662.                 cmp  ax,[sbpsp]            ;compare to address of owner
  663.                 ja   sbsystem              ;if owner below SB, system-owned
  664.  
  665.                 add  ax,[sblength]         ;add in length
  666.                 cmp  ax,[sbpsp]            ;compare to owner's PSP
  667.                 JB   sbnotprogram          ;if end below owner PSP, no program
  668.                 cmp  [sblength],10         ;is block long enough to have a psp?
  669.                 jbe  sbnotprogram          ;if not, no program
  670.  
  671.                 mov  dx,offset sbprogmsg   ;type out formatted data
  672.                 call typestring
  673.  
  674.                 call progtype
  675.  
  676.                 mov  dx,offset sbproghead   ;type out formatted data
  677.                 jmp  sbjoin                                              
  678.  
  679. sbglobalenv:      
  680.                 mov  dx,offset sbglobalmsg   ;say it is global envrionment
  681.                 call typestring
  682.                 push es
  683.                 call sbinc
  684.                 call progtypeenv             ;type out environment
  685.                 pop  es                     
  686.                 mov  dx,offset sbdatahead    ;type heading for hex data
  687.                 jmp  sbjoin                                              
  688. sbsystem:      
  689.                 mov  dx,offset sbsystemmsg   ;say it belongs to the system
  690.                 call typestring
  691.                 mov  dx,offset sbdatahead    ;type heading for hex data
  692.                 jmp  sbjoin                                              
  693.  
  694. sbnotprogram:
  695.                 mov  dx,offset sbnotprogmsg   ;say it is not a program
  696.                 call typestring
  697.                 mov  dx,offset sbdatahead     ;type heading for hex data
  698.                 jmp  sbjoin                                              
  699. sbfree:
  700.                 mov  dx,offset sbfreemsg      ;say it is free storage
  701.                 call typestring
  702.                 mov  dx,offset sbdatahead     ;type heading for hex data
  703.                 jmp  sbjoin                                              
  704.  
  705. sbconfig:
  706.                 mov  dx,offset sbconfigmsg     ;say it belongs to config.sys
  707.                 call typestring
  708.                 mov  dx,offset sbdatahead      ;type heading for hex data
  709.  
  710. sbjoin:
  711.                 call typestring
  712.  
  713. sbdisplay:
  714.                 mov  cx,[sblength]         ;format first 16 or less paragraphs
  715.                 cmp  cx,16
  716.                 jb   sbsmall
  717.                 mov  cx,16
  718. sbsmall:        
  719.                 push es                    ;save ES:
  720. sbloop:         
  721.                 mov  ax,es
  722.                 inc  ax 
  723.                 mov  es,ax
  724.                 call hextype
  725.                 loop sbloop
  726.  
  727. sbexit:
  728.  
  729.                 pop  es                    ;restore registers
  730.                 pop  dx
  731.                 pop  cx
  732.                 pop  ax
  733.                 ret
  734.  
  735. sbtype          endp
  736.  
  737. badblok_msg     db    'Bad storage block encountered',cr,lf,'$'
  738. lastblok_msg    db    'End of storage block chain reached',cr,lf,'$'
  739. baddos_msg      db    'Must be running under DOS 2.0 or above',cr,lf,'$'
  740.  
  741. program:              ;this is the actual main line program
  742.  
  743.                 mov   ah,30h         ;get release number
  744.                 int   21h
  745.                 cmp   al,01h         ;above dos 1.x?
  746.                 jna   baddos
  747.  
  748.                 cld              ;clear direction flag
  749.                 call  getfirstsb  ;ES points to first SB
  750.  
  751. sblook:                          ;loop all storage blocks
  752.                 MOV   al,sbkind   ;get storage block type byte
  753.                 cmp   al,04dh     ;ordinary storage block
  754.                 je    gotblok 
  755.  
  756.                 cmp   al,05ah
  757.                 je    lastblok    ;last storage block
  758.  
  759.                 jmp   badblok
  760. gotblok:       
  761.  
  762.                 mov   dx,offset sbhead      ;type out formatted data 
  763.                 call  typestring 
  764.  
  765.                 call  hextype
  766.  
  767.                 call  sbtype
  768.  
  769.                 call  getnextsb
  770.  
  771.                 mov   dx,offset  crlf
  772.                 call  typestring
  773.  
  774.                 jmp   sblook 
  775. lastblok:
  776.                 call  hextype
  777.  
  778.                 call  sbtype
  779.  
  780.                 mov   dx,offset lastblok_msg
  781.                 jmp   sendmsg
  782.  
  783. baddos:
  784.                 mov   dx,offset baddos_msg
  785.                 jmp   sendmsg
  786.  
  787. badblok:
  788.                 call  hextype
  789.  
  790.                 mov   dx,offset badblok_msg
  791. sendmsg:             
  792.                 call  typestring
  793.                 
  794.                 INT   20h                                 
  795.       code      ENDP
  796.       code_seg  ENDS
  797.                 END   code
  798.  
  799.  
  800.  
  801.  
  802.  
  803.  
  804.  
  805. ]├Uï∞ï ∩≤3▓√Cèëùë>wë6y╬ë{úâ3╔ █u1╟ü
  806. Φrêuï6yΦñ
  807. u≈â  u≈┴BtÇ╔0íàïç├ëüΦ$ëuVΦ▀ 7Ç╔0δ%Ç╔0¥u≈█≈à▀